#ifndef __MPQ_H__
#define __MPQ_H__

#include "OgrePrerequisites.h"

#include "OgreArchive.h"
#include "OgreArchiveFactory.h"
#include <Windows.h>

namespace Ogre {

	class _OgreExport MPQArchive : public Archive
	{
	protected:
		HANDLE mhMPQ;
		/// Handle any errors
		void checkMPQError(int nError, const String& operation) const;
		/// File list (since zziplib seems to only allow scanning of dir tree once)
		FileInfoList mFileList;
	public:
		MPQArchive(const String& name, const String& archType );
		~MPQArchive();

		virtual bool isCaseSensitive(void) const { return false; }

		virtual void load();

		virtual void unload();

		virtual DataStreamPtr open(const String& filename) const;

		virtual StringVectorPtr list(bool recursive = true, bool dirs = false);

		virtual FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false);

		virtual StringVectorPtr find(const String& pattern, bool recursive = true,
			bool dirs = false);

		virtual bool exists(const String& filename); 

		virtual time_t getModifiedTime(const String& filename); 

		virtual FileInfoListPtr findFileInfo(const String& pattern, 
			bool recursive = true, bool dirs = false);
	};

	class _OgrePrivate MPQArchiveFactory : public ArchiveFactory
	{
	public:
		virtual ~MPQArchiveFactory() {}
		/// @copydoc FactoryObj::getType
		virtual const String& getType() const;
		/// @copydoc FactoryObj::createInstance
		virtual Archive *createInstance( const String& name ) 
		{
			return OGRE_NEW MPQArchive(name, "MPQ");
		}
		/// @copydoc FactoryObj::destroyInstance
		virtual void destroyInstance( Archive* arch) { OGRE_DELETE arch; }
	};

	class _OgrePrivate MPQDataStream : public DataStream
	{
	protected:
		HANDLE mhFile;
	public:
		/// Unnamed constructor
		MPQDataStream(HANDLE hFile, size_t uncompressedSize);
		/// Constructor for creating named streams
		MPQDataStream(const String& name, HANDLE hFile, size_t uncompressedSize);
		~MPQDataStream();
		/// @copydoc DataStream::read
		size_t read(void* buf, size_t count);
		/// @copydoc DataStream::skip
		void skip(long count);
		/// @copydoc DataStream::seek
		void seek( size_t pos );
		/// @copydoc DataStream::seek
		size_t tell(void) const;
		/// @copydoc DataStream::eof
		bool eof(void) const;
		/// @copydoc DataStream::close
		void close(void);
	};

}

#endif